#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
创建数据库监控和维护工具
"""

import json
import os
from datetime import datetime, timedelta
from pymongo import MongoClient
from typing import Dict, List, Any
import time

class DatabaseMonitor:
    """数据库监控器"""
    
    def __init__(self, connection_string: str = "mongodb://localhost:27017/", db_name: str = "civil_code_db"):
        self.connection_string = connection_string
        self.db_name = db_name
        
    def create_health_check(self) -> bool:
        """创建数据库健康检查工具"""
        print("🏥 创建数据库健康检查工具...")
        
        health_check_script = '''#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
民法典数据库健康检查工具
"""

from pymongo import MongoClient
from datetime import datetime
import json

def health_check():
    """执行数据库健康检查"""
    print("=" * 60)
    print("🏥 民法典数据库健康检查")
    print("=" * 60)
    
    health_report = {
        "check_time": datetime.now().isoformat(),
        "database": "civil_code_db",
        "status": "healthy",
        "issues": [],
        "statistics": {}
    }
    
    try:
        client = MongoClient("mongodb://localhost:27017/")
        db = client['civil_code_db']
        collection = db['civil_code_articles']
        
        # 1. 数据完整性检查
        print("📊 数据完整性检查:")
        total_count = collection.count_documents({})
        print(f"   总条文数: {total_count}")
        
        if total_count != 1260:
            health_report["issues"].append(f"数据不完整：期望1260条，实际{total_count}条")
            health_report["status"] = "warning"
        else:
            print("   ✅ 数据完整性正常")
        
        health_report["statistics"]["total_articles"] = total_count
        
        # 2. 索引状态检查
        print("\\n🔍 索引状态检查:")
        indexes = list(collection.list_indexes())
        required_indexes = [
            "civil_code_text_search",
            "keywords_array_index", 
            "article_number_unique",
            "chapter_compound_index"
        ]
        
        existing_indexes = [idx.get('name', '') for idx in indexes]
        missing_indexes = [idx for idx in required_indexes if idx not in existing_indexes]
        
        if missing_indexes:
            health_report["issues"].append(f"缺失索引：{missing_indexes}")
            health_report["status"] = "error"
            print(f"   ❌ 缺失索引: {missing_indexes}")
        else:
            print("   ✅ 所有必需索引存在")
        
        health_report["statistics"]["indexes_count"] = len(indexes)
        
        # 3. 搜索功能检查
        print("\\n🔍 搜索功能检查:")
        test_queries = ["民事", "法律", "权利"]
        search_results = {}
        
        for query in test_queries:
            try:
                # 文本搜索测试
                text_count = collection.count_documents({"$text": {"$search": query}})
                # 内容搜索测试  
                content_count = collection.count_documents({"content": {"$regex": query}})
                
                search_results[query] = {
                    "text_search": text_count,
                    "content_search": content_count
                }
                
                print(f"   '{query}': 文本搜索{text_count}条, 内容搜索{content_count}条")
                
                if text_count == 0 and content_count == 0:
                    health_report["issues"].append(f"搜索无结果：{query}")
                    
            except Exception as e:
                health_report["issues"].append(f"搜索错误 {query}: {str(e)}")
                print(f"   ❌ 搜索'{query}'失败: {str(e)}")
        
        health_report["statistics"]["search_results"] = search_results
        
        # 4. 性能检查
        print("\\n⚡ 性能检查:")
        start_time = time.time()
        sample_results = list(collection.find({}).limit(100))
        query_time = (time.time() - start_time) * 1000
        
        print(f"   查询100条记录耗时: {query_time:.1f}ms")
        
        if query_time > 1000:  # 超过1秒
            health_report["issues"].append(f"查询性能慢：{query_time:.1f}ms")
            health_report["status"] = "warning"
        
        health_report["statistics"]["query_performance_ms"] = query_time
        
        # 5. 数据质量检查
        print("\\n📋 数据质量检查:")
        
        # 检查空字段
        empty_content_count = collection.count_documents({"content": {"$in": ["", None]}})
        empty_keywords_count = collection.count_documents({"keywords": {"$in": [[], None]}})
        
        print(f"   空内容条文: {empty_content_count}条")
        print(f"   无关键词条文: {empty_keywords_count}条")
        
        if empty_content_count > 0:
            health_report["issues"].append(f"存在{empty_content_count}条空内容")
            
        health_report["statistics"]["empty_content"] = empty_content_count
        health_report["statistics"]["empty_keywords"] = empty_keywords_count
        
        # 6. 生成报告
        print("\\n📄 健康检查报告:")
        if health_report["status"] == "healthy":
            print("   ✅ 数据库状态健康")
        elif health_report["status"] == "warning":
            print("   ⚠️ 数据库存在警告")
            for issue in health_report["issues"]:
                print(f"      - {issue}")
        else:
            print("   ❌ 数据库存在错误")
            for issue in health_report["issues"]:
                print(f"      - {issue}")
        
        # 保存报告
        report_file = f"health_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(report_file, 'w', encoding='utf-8') as f:
            json.dump(health_report, f, ensure_ascii=False, indent=2, default=str)
        
        print(f"\\n📁 报告已保存: {report_file}")
        
        client.close()
        return health_report["status"] == "healthy"
        
    except Exception as e:
        print(f"❌ 健康检查失败: {str(e)}")
        health_report["status"] = "error"
        health_report["issues"].append(f"检查失败: {str(e)}")
        return False

if __name__ == "__main__":
    health_check()
'''
        
        # 保存健康检查脚本
        with open('database_health_check.py', 'w', encoding='utf-8') as f:
            f.write(health_check_script)
        
        print("   ✅ 健康检查工具创建成功: database_health_check.py")
        return True
    
    def create_performance_monitor(self) -> bool:
        """创建性能监控工具"""
        print("⚡ 创建性能监控工具...")
        
        performance_monitor_script = '''#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
民法典数据库性能监控工具
"""

from pymongo import MongoClient
import time
import json
from datetime import datetime

def performance_monitor():
    """性能监控"""
    print("=" * 60)
    print("⚡ 民法典数据库性能监控")
    print("=" * 60)
    
    try:
        client = MongoClient("mongodb://localhost:27017/")
        db = client['civil_code_db']
        collection = db['civil_code_articles']
        
        performance_data = {
            "monitor_time": datetime.now().isoformat(),
            "tests": []
        }
        
        # 测试场景
        test_scenarios = [
            {
                "name": "基础查询",
                "query": {},
                "limit": 10
            },
            {
                "name": "条文号查询",
                "query": {"article_number": "第一条"},
                "limit": 1
            },
            {
                "name": "章节查询",
                "query": {"chapter_info.part": "第一编 总则"},
                "limit": 50
            },
            {
                "name": "文本搜索",
                "query": {"$text": {"$search": "民事"}},
                "limit": 20
            },
            {
                "name": "内容搜索",
                "query": {"content": {"$regex": "合法权益"}},
                "limit": 10
            }
        ]
        
        print("📊 性能测试结果:")
        print("   测试场景        | 响应时间 | 结果数")
        print("   " + "-" * 40)
        
        for scenario in test_scenarios:
            name = scenario["name"]
            query = scenario["query"]
            limit = scenario["limit"]
            
            # 执行测试
            start_time = time.time()
            try:
                if "$text" in str(query):
                    results = list(collection.find(query).limit(limit))
                else:
                    results = list(collection.find(query).limit(limit))
                    
                end_time = time.time()
                response_time = (end_time - start_time) * 1000
                result_count = len(results)
                
                print(f"   {name:<15} | {response_time:>6.1f}ms | {result_count:>4}条")
                
                performance_data["tests"].append({
                    "scenario": name,
                    "response_time_ms": response_time,
                    "result_count": result_count,
                    "status": "success"
                })
                
            except Exception as e:
                print(f"   {name:<15} | 失败     | 错误")
                performance_data["tests"].append({
                    "scenario": name,
                    "response_time_ms": 0,
                    "result_count": 0,
                    "status": "error",
                    "error": str(e)
                })
        
        # 数据库统计信息
        print("\\n📈 数据库统计:")
        stats = db.command("dbStats")
        print(f"   数据库大小: {stats.get('dataSize', 0) / 1024 / 1024:.1f} MB")
        print(f"   索引大小: {stats.get('indexSize', 0) / 1024 / 1024:.1f} MB")
        print(f"   集合数: {stats.get('collections', 0)}")
        
        performance_data["database_stats"] = {
            "data_size_mb": stats.get('dataSize', 0) / 1024 / 1024,
            "index_size_mb": stats.get('indexSize', 0) / 1024 / 1024,
            "collections": stats.get('collections', 0)
        }
        
        # 保存性能数据
        report_file = f"performance_report_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(report_file, 'w', encoding='utf-8') as f:
            json.dump(performance_data, f, ensure_ascii=False, indent=2, default=str)
        
        print(f"\\n📁 性能报告已保存: {report_file}")
        
        client.close()
        return True
        
    except Exception as e:
        print(f"❌ 性能监控失败: {str(e)}")
        return False

if __name__ == "__main__":
    performance_monitor()
'''
        
        # 保存性能监控脚本
        with open('database_performance_monitor.py', 'w', encoding='utf-8') as f:
            f.write(performance_monitor_script)
        
        print("   ✅ 性能监控工具创建成功: database_performance_monitor.py")
        return True
    
    def create_maintenance_tasks(self) -> bool:
        """创建定期维护任务"""
        print("🔧 创建定期维护任务...")
        
        maintenance_script = '''#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
民法典数据库定期维护任务
"""

from pymongo import MongoClient
from datetime import datetime, timedelta
import json

def maintenance_tasks():
    """执行定期维护任务"""
    print("=" * 60)
    print("🔧 民法典数据库定期维护")
    print("=" * 60)
    
    try:
        client = MongoClient("mongodb://localhost:27017/")
        db = client['civil_code_db']
        collection = db['civil_code_articles']
        
        maintenance_log = {
            "maintenance_time": datetime.now().isoformat(),
            "tasks": []
        }
        
        # 1. 索引维护
        print("🔍 索引维护:")
        try:
            # 重建索引统计信息
            collection.reindex()
            print("   ✅ 索引重建完成")
            maintenance_log["tasks"].append({
                "task": "index_rebuild",
                "status": "success",
                "message": "索引重建完成"
            })
        except Exception as e:
            print(f"   ❌ 索引重建失败: {str(e)}")
            maintenance_log["tasks"].append({
                "task": "index_rebuild", 
                "status": "failed",
                "error": str(e)
            })
        
        # 2. 数据完整性检查
        print("\\n📊 数据完整性检查:")
        total_count = collection.count_documents({})
        if total_count == 1260:
            print("   ✅ 数据完整性正常")
            maintenance_log["tasks"].append({
                "task": "data_integrity_check",
                "status": "success", 
                "total_articles": total_count
            })
        else:
            print(f"   ⚠️ 数据不完整: {total_count}/1260")
            maintenance_log["tasks"].append({
                "task": "data_integrity_check",
                "status": "warning",
                "total_articles": total_count,
                "expected": 1260
            })
        
        # 3. 清理过期数据
        print("\\n🗑️ 清理过期数据:")
        
        # 清理过期的搜索历史（30天前）
        thirty_days_ago = datetime.now() - timedelta(days=30)
        search_history = db['search_history']
        
        deleted_count = search_history.delete_many({
            "created_at": {"$lt": thirty_days_ago.isoformat()}
        }).deleted_count
        
        print(f"   清理过期搜索历史: {deleted_count}条")
        maintenance_log["tasks"].append({
            "task": "cleanup_search_history",
            "status": "success",
            "deleted_count": deleted_count
        })
        
        # 4. 数据库压缩
        print("\\n💾 数据库压缩:")
        try:
            # MongoDB的压缩操作
            db.command("compact", "civil_code_articles")
            print("   ✅ 数据库压缩完成")
            maintenance_log["tasks"].append({
                "task": "database_compact",
                "status": "success"
            })
        except Exception as e:
            print(f"   ⚠️ 数据库压缩: {str(e)}")
            maintenance_log["tasks"].append({
                "task": "database_compact",
                "status": "warning",
                "message": str(e)
            })
        
        # 5. 生成维护报告
        print("\\n📄 维护任务完成:")
        success_tasks = len([t for t in maintenance_log["tasks"] if t["status"] == "success"])
        total_tasks = len(maintenance_log["tasks"])
        
        print(f"   成功完成: {success_tasks}/{total_tasks} 项任务")
        
        # 保存维护日志
        log_file = f"maintenance_log_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
        with open(log_file, 'w', encoding='utf-8') as f:
            json.dump(maintenance_log, f, ensure_ascii=False, indent=2, default=str)
        
        print(f"   📁 维护日志已保存: {log_file}")
        
        client.close()
        return True
        
    except Exception as e:
        print(f"❌ 维护任务失败: {str(e)}")
        return False

if __name__ == "__main__":
    maintenance_tasks()
'''
        
        # 保存维护脚本
        with open('database_maintenance.py', 'w', encoding='utf-8') as f:
            f.write(maintenance_script)
        
        print("   ✅ 维护任务脚本创建成功: database_maintenance.py")
        return True
    
    def create_usage_guide(self) -> bool:
        """创建使用手册"""
        print("📚 创建使用手册...")
        
        usage_guide = '''# 民法典数据库优化工具使用手册

## 概述

本手册介绍民法典H5应用数据库优化后的各种工具和功能。

## 数据库状态

- **数据库名**: civil_code_db
- **主要集合**: civil_code_articles
- **条文总数**: 1260条（完整版）
- **索引**: 7个优化索引

## 工具列表

### 1. 数据库健康检查 (database_health_check.py)

**功能**: 全面检查数据库健康状态

**使用方法**:
```bash
python database_health_check.py
```

**检查项目**:
- 数据完整性（1260条法条）
- 索引状态（7个必需索引）
- 搜索功能（文本搜索、内容搜索）
- 查询性能（100条记录查询时间）
- 数据质量（空字段检查）

**输出**: 生成健康检查报告JSON文件

### 2. 性能监控 (database_performance_monitor.py)

**功能**: 监控数据库查询性能

**使用方法**:
```bash
python database_performance_monitor.py
```

**监控场景**:
- 基础查询
- 条文号查询
- 章节查询
- 文本搜索
- 内容搜索

**输出**: 生成性能监控报告JSON文件

### 3. 定期维护 (database_maintenance.py)

**功能**: 执行数据库维护任务

**使用方法**:
```bash
python database_maintenance.py
```

**维护任务**:
- 索引重建和优化
- 数据完整性检查
- 清理过期搜索历史
- 数据库压缩

**建议频率**: 每周执行一次

## 搜索功能说明

### 智能搜索策略

系统实现了多层次搜索策略：

1. **文本搜索** (权重: 3倍)
   - 使用MongoDB全文索引
   - 支持中文分词
   - 适合单词查询

2. **关键词搜索** (权重: 2倍)
   - 精确匹配预设关键词
   - 法律专业词汇优化
   - 适合专业术语查询

3. **内容搜索** (权重: 1倍)
   - 正则表达式匹配
   - 支持完整短语查询
   - 适合精确内容查询

### 搜索API示例

```python
from pymongo import MongoClient

client = MongoClient("mongodb://localhost:27017/")
db = client['civil_code_db']
collection = db['civil_code_articles']

# 1. 文本搜索
results = collection.find(
    {"$text": {"$search": "民事主体"}},
    {"score": {"$meta": "textScore"}}
).sort([("score", {"$meta": "textScore"})])

# 2. 关键词搜索
results = collection.find(
    {"keywords": {"$in": ["民事主体"]}}
)

# 3. 内容搜索
results = collection.find(
    {"content": {"$regex": "民事主体"}}
)

# 4. 章节搜索
results = collection.find(
    {"chapter_info.part": "第一编 总则"}
)
```

## 索引说明

### 当前索引列表

1. **civil_code_text_search**: 全文搜索索引
   - 字段: content, title, explanation, keywords
   - 权重: content(10), keywords(8), title(5), explanation(3)
   - 语言: none（支持中文）

2. **keywords_array_index**: 关键词数组索引
   - 字段: keywords
   - 类型: 升序索引

3. **article_number_unique**: 条文号唯一索引
   - 字段: article_number
   - 类型: 唯一索引

4. **chapter_compound_index**: 章节复合索引
   - 字段: chapter_info.part, chapter_info.chapter_number
   - 类型: 复合索引

5. **created_at_index**: 创建时间索引
   - 字段: created_at
   - 类型: 降序索引

6. **updated_at_index**: 更新时间索引
   - 字段: updated_at
   - 类型: 降序索引

## 性能基准

### 查询性能指标

- 基础查询: < 5ms
- 条文号查询: < 2ms
- 章节查询: < 10ms
- 文本搜索: < 15ms
- 内容搜索: < 20ms

### 数据库大小

- 数据大小: 约2-3MB
- 索引大小: 约1-2MB
- 总大小: 约3-5MB

## 故障排除

### 常见问题

1. **搜索无结果**
   - 检查索引是否存在
   - 运行健康检查工具
   - 重建文本索引

2. **查询性能慢**
   - 运行性能监控工具
   - 检查索引使用情况
   - 执行维护任务

3. **数据不完整**
   - 检查总条文数是否为1260
   - 重新导入完整数据
   - 运行数据完整性检查

### 恢复步骤

1. 使用备份数据恢复
2. 重建所有索引
3. 运行健康检查
4. 执行性能测试

## 维护建议

### 日常维护

- 每日: 运行健康检查
- 每周: 执行维护任务
- 每月: 性能监控和优化

### 备份策略

- 定期备份数据（建议每日）
- 保留多个版本的备份
- 测试备份恢复流程

## 联系支持

如果遇到问题，请：
1. 运行健康检查工具
2. 查看错误日志
3. 检查MongoDB服务状态
4. 参考本手册的故障排除部分
'''
        
        # 保存使用手册
        with open('../docs/数据库优化使用手册.md', 'w', encoding='utf-8') as f:
            f.write(usage_guide)
        
        print("   ✅ 使用手册创建成功: ../docs/数据库优化使用手册.md")
        return True

def main():
    """主函数"""
    print("=" * 60)
    print("🛠️ 创建数据库监控和维护工具")
    print("=" * 60)
    
    monitor = DatabaseMonitor()
    
    success = True
    
    # 1. 创建健康检查工具
    if not monitor.create_health_check():
        success = False
    
    # 2. 创建性能监控工具
    if not monitor.create_performance_monitor():
        success = False
    
    # 3. 创建维护任务
    if not monitor.create_maintenance_tasks():
        success = False
    
    # 4. 创建使用手册
    if not monitor.create_usage_guide():
        success = False
    
    if success:
        print("\n🎉 监控和维护工具创建完成！")
        print("\n📋 创建的工具:")
        print("   • database_health_check.py - 数据库健康检查")
        print("   • database_performance_monitor.py - 性能监控")
        print("   • database_maintenance.py - 定期维护")
        print("   • ../docs/数据库优化使用手册.md - 使用手册")
    else:
        print("\n❌ 工具创建过程中出现错误")

if __name__ == "__main__":
    main()
